home *** CD-ROM | disk | FTP | other *** search
/ IRIX 6.2 Applications 1996 May / SGI IRIX 6.2 Applications 1996 May.iso / dist / impr_dev.idb / usr / impressario / src / libstiff / printstiff.c.z / printstiff.c
C/C++ Source or Header  |  1996-05-06  |  15KB  |  521 lines

  1. /**************************************************************************
  2.  *
  3.  *           Copyright (c)    1992 Silicon Graphics, Inc.
  4.  *            All Rights Reserved
  5.  *
  6.  *       THIS    IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SGI
  7.  *
  8.  * The copyright notice above does not evidence any actual of intended
  9.  * publication of such source code, and is an unpublished work by Silicon
  10.  * Graphics, Inc. This material contains CONFIDENTIAL INFORMATION that is
  11.  * the property of Silicon Graphics, Inc. Any use, duplication or
  12.  * disclosure not specifically authorized by Silicon Graphics is strictly
  13.  * prohibited.
  14.  *
  15.  * RESTRICTED RIGHTS LEGEND:
  16.  *
  17.  * Use, duplication or disclosure by the Government is subject to
  18.  * restrictions as set forth in subdivision (c)(1)(ii) of the Rights in
  19.  * Technical Data and Computer Software clause at DFARS 52.227-7013,
  20.  * and/or in similar or successor clauses in the FAR, DOD or NASA FAR
  21.  * Supplement. Unpublished - rights reserved under the Copyright Laws of
  22.  * the United States. Contractor is SILICON GRAPHICS, INC., 2011 N.
  23.  * Shoreline Blvd., Mountain View, CA 94039-7311
  24.  **************************************************************************
  25.  *
  26.  * File: printstiff.c
  27.  *
  28.  * Description: Support for the printing STIFF API. This API is built
  29.  *    on the base STIFF API. Functions in this API (PST) can be
  30.  *    freely mixed with functions in the base STIFF API (ST).
  31.  *
  32.  *    The PST functions simply write IFD's with more tags. These tags
  33.  *    specify information relevant to image files destined for
  34.  *    printers.
  35.  *
  36.  **************************************************************************/
  37.  
  38.  
  39. #ident "$Revision: 1.8 $"
  40.  
  41.  
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <string.h>
  45. #include <bstring.h>
  46. #include "printstiff.h"
  47. #include "stiffp.h"
  48.  
  49.  
  50. /* Private data block structure */
  51.  
  52. typedef struct {
  53.     PSTPrivateData *items;
  54.     unsigned long amount;
  55. } PRIVATE_DATA;
  56.  
  57.  
  58. /* Local functions */
  59.  
  60. static int add_private_data(PRIVATE_DATA*, unsigned short, STTagType,
  61.                         unsigned long, void*);
  62. static int get_private_data(PRIVATE_DATA*, unsigned short, STTagType*,
  63.                         unsigned long*, void**);
  64. static void free_private_data(PRIVATE_DATA*);
  65. static int create_private_tag(STStream*, PRIVATE_DATA*);
  66.  
  67.  
  68. /**************************************************************************
  69.  *
  70.  * Function: PSTWriteImageHeader
  71.  *
  72.  * Description: Writes a Print STIFF image file header. This is a STIFF
  73.  *    IFD with additional tags.
  74.  *
  75.  * Parameters: 
  76.  *    st (I) - STIFF stream pointer
  77.  *    pst_hdp (I) - pointer to a filled in Print STIFF header structure
  78.  *    last (I) - 1 = last IFD to write, 0 = still more IFDs to come
  79.  *
  80.  * Return: 0 if successful and -1 if error.
  81.  *
  82.  **************************************************************************/
  83.  
  84. #define ADD_TAG(tag, type, len, datap) \
  85.     if (STAddTag(st, tag, type, len, (void*)(datap)) < 0) { \
  86.         return -1; \
  87.     }
  88.  
  89. #define ADD_PDATA(id, type, len, datap) \
  90.     if (add_private_data(&write_pblock, id, type, len, (void*)(datap)) < 0) { \
  91.     return -1; \
  92.     }
  93.  
  94. int PSTWriteImageHeader(STStream *st, PSTImageHeader *pst_hdp, int last)
  95. {
  96.     STImageHeader st_hd;
  97.     int status;
  98.     unsigned long res[2];
  99.     unsigned long subfile = 0;
  100.     static PRIVATE_DATA write_pblock;
  101.  
  102.     /*
  103.      * Set up an ST header
  104.      */
  105.     st_hd.width = pst_hdp->width;
  106.     st_hd.height = pst_hdp->height;
  107.     st_hd.bitsPerSample = pst_hdp->bitsPerSample;
  108.     st_hd.samplesPerPixel = pst_hdp->samplesPerPixel;
  109.     st_hd.imgbytes = pst_hdp->imgbytes;
  110.     st_hd.type = pst_hdp->type;
  111.     st_hd.plane = pst_hdp->plane;
  112.  
  113.     /*
  114.      * Add tags for printing IFD
  115.      */
  116.  
  117.     /* New Subfile Type */
  118.     subfile |= 0x2;        /* Subfile is single page of multi-page doc */
  119.     ADD_TAG(STNewSubfileType, ST_TAG_TYPE_LONG, 1, &subfile);
  120.  
  121.     /* Resolution unit */
  122.     ADD_TAG(STResolutionUnit, ST_TAG_TYPE_SHORT, 1, &pst_hdp->resUnit);
  123.  
  124.     /* X Resolution */
  125.     res[0] = (unsigned long)pst_hdp->xRes;
  126.     res[1] = 1;
  127.     ADD_TAG(STXResolution, ST_TAG_TYPE_RATIONAL, 1, res);
  128.  
  129.     /* Y Resolution */
  130.     res[0] = (unsigned long)pst_hdp->yRes;
  131.     res[1] = 1;
  132.     ADD_TAG(STYResolution, ST_TAG_TYPE_RATIONAL, 1, res);
  133.  
  134.     /* Thresholding */
  135.     ADD_TAG(STThresholding, ST_TAG_TYPE_SHORT, 1, &pst_hdp->thresholding);
  136.  
  137.     /* Compression */
  138.     ADD_TAG(STCompression, ST_TAG_TYPE_SHORT, 1, &pst_hdp->compression);
  139.  
  140.     /* Date and Time Stamp */
  141.     if (pst_hdp->dateTime && *(pst_hdp->dateTime)) {
  142.         ADD_TAG(STDateTime, ST_TAG_TYPE_ASCII, 20, pst_hdp->dateTime);
  143.     }
  144.  
  145.     /* Host Computer */
  146.     if (pst_hdp->hostComputer && *(pst_hdp->hostComputer)) {
  147.         ADD_TAG(STHostComputer, ST_TAG_TYPE_ASCII,
  148.         strlen(pst_hdp->hostComputer) + 1, pst_hdp->hostComputer);
  149.     }
  150.  
  151.     /* Software */
  152.     if (pst_hdp->software && *(pst_hdp->software)) {
  153.         ADD_TAG(STSoftware, ST_TAG_TYPE_ASCII,
  154.         strlen(pst_hdp->software) + 1, pst_hdp->software);
  155.     }
  156.  
  157.     /* Document Name */
  158.     if (pst_hdp->docName && *(pst_hdp->docName)) {
  159.         ADD_TAG(STDocumentName, ST_TAG_TYPE_ASCII,
  160.         strlen(pst_hdp->docName) + 1, pst_hdp->docName);
  161.     }
  162.  
  163.     /* Page Number */
  164.     ADD_TAG(STPageNumber, ST_TAG_TYPE_SHORT, 2, pst_hdp->pageNumbers);
  165.  
  166.     /* Target Printer */
  167.     if (pst_hdp->targetPrinter && *(pst_hdp->targetPrinter)) {
  168.         ADD_TAG(STTargetPrinter, ST_TAG_TYPE_ASCII,
  169.         strlen(pst_hdp->targetPrinter) + 1, pst_hdp->targetPrinter);
  170.     }
  171.  
  172.     /*
  173.      * Add SGI private data into the IFD. Currently we must call
  174.      * add_private_data with tags in ascending order.
  175.      */
  176.     
  177.     /* Ensure that we start clean so free the private data block */
  178.     free_private_data(&write_pblock);
  179.  
  180.     /* Driver Options */
  181.     if (pst_hdp->driverOptions && *(pst_hdp->driverOptions)) {
  182.     ADD_PDATA(PSTPrivateDriverOptions, ST_TAG_TYPE_ASCII,
  183.         strlen(pst_hdp->driverOptions)+1, pst_hdp->driverOptions);
  184.     }
  185.  
  186.     /* Put private data into the IFD */
  187.     if (create_private_tag(st, &write_pblock) < 0)
  188.     return -1;
  189.  
  190.     /* Free the private data block */
  191.     free_private_data(&write_pblock);
  192.  
  193.     /*
  194.      * Write the IFD
  195.      */
  196.     status = STWriteImageHeader(st, &st_hd, last);
  197.  
  198.     return status;
  199. }
  200.  
  201. #undef ADD_TAG
  202.  
  203.  
  204. /**************************************************************************
  205.  *
  206.  * Function: PSTReadImageHeader
  207.  *
  208.  * Description: Reads a Print STIFF image file header. This is a STIFF
  209.  *    IFD with additional tags.
  210.  *
  211.  * Parameters: 
  212.  *    st (I) - STIFF stream pointer
  213.  *    pst_hdp (I) - pointer to a Print STIFF header structure
  214.  *
  215.  * Return: 0 if successful and -1 if error.
  216.  *
  217.  **************************************************************************/
  218.  
  219. #define GET_TAG(tag)        STGetTag(st, tag, &type, &len, &val)
  220.  
  221. #define GET_PDATA(id)    get_private_data(&read_pblock, id, &type, &len, &val)
  222.  
  223. int PSTReadImageHeader(STStream *st, PSTImageHeader *pst_hdp)
  224. {
  225.     STImageHeader st_hd;
  226.     STTagType type;
  227.     unsigned long len;
  228.     void *val;
  229.     static PRIVATE_DATA read_pblock;
  230.  
  231.     /*
  232.      * Clear the header in case not all tags
  233.      * are found
  234.      */
  235.     bzero((void*)pst_hdp, sizeof(PSTImageHeader));
  236.  
  237.     /*
  238.      * Read the IFD
  239.      */
  240.     if (STReadImageHeader(st, &st_hd) < 0)
  241.     return -1;
  242.  
  243.     /*
  244.      * Fill in the structure with what we got back
  245.      */
  246.     pst_hdp->width = st_hd.width;
  247.     pst_hdp->height = st_hd.height;
  248.     pst_hdp->bitsPerSample = st_hd.bitsPerSample;
  249.     pst_hdp->samplesPerPixel = st_hd.samplesPerPixel;
  250.     pst_hdp->imgbytes = st_hd.imgbytes;
  251.     pst_hdp->type = st_hd.type;
  252.     pst_hdp->plane = st_hd.plane;
  253.  
  254.     /*
  255.      * Get printing specific tags, if any. If tag is
  256.      * not found don't stop, set field to default if
  257.      * available and move on to next tag. We don't want
  258.      * the read to fail if we are reading a base STIFF file
  259.      */
  260.  
  261.     /* Resolution unit */
  262.     pst_hdp->resUnit = (GET_TAG(STResolutionUnit) < 0) ?
  263.                 PST_RES_UNIT_INCH: *((PSTResUnit*)val);
  264.  
  265.     /* X Resolution */
  266.     if (GET_TAG(STXResolution) == 0)
  267.     pst_hdp->xRes = ((long*)val)[0] / ((long*)val)[1];
  268.  
  269.     /* Y Resolution */
  270.     if (GET_TAG(STYResolution) == 0)
  271.     pst_hdp->yRes = ((long*)val)[0] / ((long*)val)[1];
  272.  
  273.     /* Thresholding */
  274.     pst_hdp->thresholding = (GET_TAG(STThresholding) < 0) ?
  275.                 PST_THRESHOLD_NONE: *((PSTThreshold*)val);
  276.  
  277.     /* Compression */
  278.     pst_hdp->compression = (GET_TAG(STCompression) < 0) ?
  279.                 PST_COMPRESSION_NONE: *((PSTCompression*)val);
  280.  
  281.     /* Date and Time Stamp */
  282.     pst_hdp->dateTime = (GET_TAG(STDateTime) < 0) ? "": (char*)val;
  283.  
  284.     /* Host Computer */
  285.     pst_hdp->hostComputer = (GET_TAG(STHostComputer) < 0) ? "": (char*)val;
  286.  
  287.     /* Software */
  288.     pst_hdp->software = (GET_TAG(STSoftware) < 0) ? "": (char*)val;
  289.  
  290.     /* Document Name */
  291.     pst_hdp->docName = (GET_TAG(STDocumentName) < 0) ? "": (char*)val;
  292.  
  293.     /* Page Number */
  294.     if (GET_TAG(STPageNumber) == 0) {
  295.     pst_hdp->pageNumbers[0] = ((short*)val)[0];
  296.     pst_hdp->pageNumbers[1] = ((short*)val)[1];
  297.     }
  298.  
  299.     /* Target Printer */
  300.     pst_hdp->targetPrinter = (GET_TAG(STTargetPrinter) < 0) ? "": (char*)val;
  301.  
  302.     /*
  303.      * Read any SGI private data and set the PST structure
  304.      * fields accordingly
  305.      */
  306.  
  307.     /* Get the private tag */
  308.     if (GET_TAG(STSGIPrinting) == 0) {
  309.     read_pblock.items = (PSTPrivateData*)val;
  310.     read_pblock.amount = len;
  311.     } else {
  312.     read_pblock.items = NULL;
  313.     read_pblock.amount = 0;
  314.     }
  315.  
  316.     /* Driver Options */
  317.     pst_hdp->driverOptions = (GET_PDATA(PSTPrivateDriverOptions) < 0) ?
  318.                                     "": (char*)val;
  319.  
  320.     return 0;
  321. }
  322.  
  323. #undef GET_TAG
  324.  
  325. /*
  326.  =========================================================================
  327.             LOCAL FUNCTIONS
  328.  =========================================================================
  329. */
  330.  
  331.  
  332. /**************************************************************************
  333.  *
  334.  * Function: add_private_data
  335.  *
  336.  * Description: Adds the specified private data item into the private
  337.  *    data item block. The block is maintained as an array and items are
  338.  *    added to the end. All data is copied into the block, there are
  339.  *    no pointers. This makes setting the private tag easier. 
  340.  *    IDs must be in ascending order so this functions must be called
  341.  *    with private IDs in ascending order. Since we have little to add 
  342.  *    this is a reasonable assumption.
  343.  *
  344.  * Parameters: 
  345.  *    pblock (I) - private data block structure
  346.  *    private_id (I) - ID of item to be added
  347.  *    type (I) - type of data item
  348.  *    len (I) - number of data items of type
  349.  *    data (I) - data to be added
  350.  *
  351.  * Return: -1 if error, 0 if success.
  352.  *
  353.  **************************************************************************/
  354.  
  355. static int add_private_data(PRIVATE_DATA *pblock, unsigned short private_id,
  356.             STTagType type, unsigned long len, void *data)
  357. {
  358.     register PSTPrivateData *pd, *ptr;
  359.     register unsigned long nItemBytes, nDataBytes;
  360.  
  361.     /*
  362.      * Calculate the number of bytes for the data item.
  363.      * this is the size of the data structure plus the amount
  364.      * of data minus 4 for dummy data item.
  365.      */
  366.     nDataBytes = len * _STTagTypeBytes(type);
  367.     nItemBytes = sizeof(PSTPrivateData) + nDataBytes - 4;
  368.  
  369.     /*
  370.      * Create an entry in the data block
  371.      */
  372.     if ((ptr = (PSTPrivateData*)((pblock->items == NULL) ? malloc(nItemBytes):
  373.         realloc(pblock->items, pblock->amount + nItemBytes))) == NULL) {
  374.     STerrno = STENOMEM;
  375.     return -1;
  376.     }
  377.     pblock->items = ptr;
  378.     /* LINTED */
  379.     pd = (PSTPrivateData*)((char*)pblock->items + pblock->amount);
  380.  
  381.     /*
  382.      * Put the data in the block
  383.      */
  384.     pd->private_id = private_id;
  385.     pd->type = type;
  386.     pd->len = len;
  387.     bcopy(data, pd->data, nDataBytes);
  388.  
  389.     /*
  390.      * Update the amount of data running total
  391.      */
  392.     pblock->amount += nItemBytes;
  393.  
  394.     return 0;
  395. }
  396.  
  397.  
  398. /**************************************************************************
  399.  *
  400.  * Function: get_private_data
  401.  *
  402.  * Description: Searches the private data block for the specified private
  403.  *    data item id. The block is assumed to be organized in ascending
  404.  *    order of private IDs.
  405.  *
  406.  * Parameters: 
  407.  *    pblock (I) - private data block to search
  408.  *    private_id (I) - private ID to search for
  409.  *    typep (O) - type of data item
  410.  *    lenp (O) - number of elements of type
  411.  *    datap (O) - pointer to item data
  412.  *
  413.  * Return: 0 if item found. -1 if item not found.
  414.  *
  415.  **************************************************************************/
  416.  
  417. static int get_private_data(PRIVATE_DATA *pblock, unsigned short id,
  418.             STTagType *typep, unsigned long *lenp, void **datap)
  419. {
  420.     register PSTPrivateData *ptr;
  421.     register unsigned long nbytes, offset = 0;
  422.  
  423.     /*
  424.      * No sense checking if there is no data
  425.      */
  426.     if (pblock->amount == 0) {
  427.     STerrno = STENOTFOUND;
  428.     return -1;
  429.     }
  430.  
  431.     /*
  432.      * Search for the id
  433.      */
  434.     while (offset < pblock->amount) {
  435.     /* LINTED */
  436.     ptr = (PSTPrivateData*)((char*)(pblock->items) + offset);
  437.     if (ptr->private_id == id) {
  438.         *typep = ptr->type;
  439.         *lenp = ptr->len;
  440.         *datap = ptr->data;
  441.         return 0;
  442.     }
  443.     if (ptr->private_id > id) {
  444.         STerrno = STENOTFOUND;
  445.         return -1;
  446.     }
  447.  
  448.         nbytes = ptr->len * _STTagTypeBytes(ptr->type);
  449.         offset += sizeof(PSTPrivateData) + nbytes - 4;
  450.     }
  451.  
  452.     STerrno = STENOTFOUND;
  453.     return -1;
  454. }
  455.  
  456.  
  457. /**************************************************************************
  458.  *
  459.  * Function: free_private_data
  460.  *
  461.  * Description: Deallocates storage for all private data.
  462.  *
  463.  * Parameters:
  464.  *    pblock (I) - private data block structure
  465.  *
  466.  * Return: none
  467.  *
  468.  **************************************************************************/
  469.  
  470. static void free_private_data(PRIVATE_DATA *pblock)
  471. {
  472.     /*
  473.      * Make sure we actually have data to free
  474.      */
  475.     if (!pblock->amount)
  476.     return;
  477.  
  478.     /*
  479.      * Free the private data
  480.      */
  481.     free(pblock->items);
  482.     pblock->items = NULL;
  483.     pblock->amount = 0;
  484. }
  485.  
  486.  
  487. /**************************************************************************
  488.  *
  489.  * Function: create_private_tag
  490.  *
  491.  * Description: Creates the SGI private data tag entry in the IFD and
  492.  *    then frees the private data block.
  493.  *
  494.  * Parameters: 
  495.  *    st (I) - STIFF stream
  496.  *    pblock (I) - private data block structure
  497.  *
  498.  * Return: -1 if error, 0 if success
  499.  *
  500.  **************************************************************************/
  501.  
  502. static int create_private_tag(STStream *st, PRIVATE_DATA *pblock)
  503. {
  504.     /*
  505.      * Make sure that there is a tag to create
  506.      */
  507.     if (!pblock->amount) {
  508.     STerrno = STENOTFOUND;
  509.     return 0;
  510.     }
  511.  
  512.     /*
  513.      * Add the tag to the IFD
  514.      */
  515.     if (STAddTag(st, STSGIPrinting, ST_TAG_TYPE_UNDEFINED,
  516.             pblock->amount, (void*)(pblock->items)) < 0)
  517.         return -1;
  518.  
  519.     return 0;
  520. }
  521.